package com.ruge.user.service.impl;

import com.ruge.core.response.Response;
import com.ruge.core.tool.RedisKeyTool;
import com.ruge.tool.str.StringTool;
import com.ruge.user.dao.BlogRepository;
import com.ruge.user.domain.model.Blog;
import com.ruge.user.domain.request.BlobFollowRequest;
import com.ruge.user.domain.request.ListBlogRequest;
import com.ruge.user.domain.request.SavaBlogRequest;
import com.ruge.user.error.UserError;
import com.ruge.user.service.BlogService;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * @author ruge.wu
 * @since 2022/2/9 15:01
 */
@Service
public class BlogServiceImpl implements BlogService {


    @Resource
    private BlogRepository blogRepository;
    @Resource
    private RedisTemplate redisTemplate;

    /**
     * 博客数据保存
     *
     * @param request {@link SavaBlogRequest}
     * @return {@link Response}
     */
    @Override
    public Response save(SavaBlogRequest request) {
        // 博客数据保存
        Long aid = request.getAid();
        Blog blog = new Blog();
        blog.setAid(aid);
        blog.setContent(request.getContent());
        Blog save = blogRepository.save(blog);
        // 获取粉丝集合
        String key = RedisKeyTool.buildFansKey(aid);
        Set<Long> members = redisTemplate.opsForSet().members(key);
        // 推送feed  -TODO 后续这里应该改造采用异步消息队列解决性能问题
        long now = System.currentTimeMillis();
        if (StringTool.isNotBlank(members)) {
            // 根据时间排序
            members.forEach(fans -> {
                redisTemplate.opsForZSet().add(RedisKeyTool.buildFansFeedKey(fans), save.getId(), now);
            });
        }
        return Response.create();
    }

    /**
     * 博客数据删除
     *
     * @param blogId 博客数据id
     * @return {@link Response}
     */
    @Override
    public Response delete(Long blogId) {
        Blog blog = blogRepository.findById(blogId).orElse(new Blog());
        if (StringTool.isBlank(blog.getId())) {
            return Response.create(UserError.BLOG_NOT_EXIST);
        }
        blog.setIsValid(false);
        blogRepository.save(blog);
        // 获取粉丝集合
        String key = RedisKeyTool.buildFansKey(blog.getAid());
        Set<Long> members = redisTemplate.opsForSet().members(key);
        // 推送feed  -TODO 后续这里应该改造采用异步消息队列解决性能问题
        if (StringTool.isNotBlank(members)) {
            // 根据时间排序
            members.forEach(fans -> {
                redisTemplate.opsForZSet().remove(RedisKeyTool.buildFansFeedKey(fans), blogId);
            });
        }
        return Response.create();
    }

    /**
     * 新增推送或取消推送 源头为关注和取关
     *
     * @param request {@link BlobFollowRequest}
     * @return {@link Response}
     */
    @Override
    public Response pipline(BlobFollowRequest request) {
        List<Blog> blogs = blogRepository.findAllByAid(request.getAid()).orElse(new ArrayList<>());
        if (StringTool.isBlank(blogs)) {
            return Response.create();
        }
        // 新增推送
        if (request.getFlag()) {
            blogs.forEach(blog -> {
                redisTemplate.opsForZSet().add(RedisKeyTool.buildFansFeedKey(request.getFriendId()), blog.getId(), blog.getCreatedTime().getTime());
            });
            // 取消推送
        } else {
            blogs.forEach(blog -> {
                redisTemplate.opsForZSet().remove(RedisKeyTool.buildFansFeedKey(request.getFriendId()), blog.getId());
            });
        }
        return Response.create();
    }

    /**
     * feed数据查询
     *
     * @param request {@link ListBlogRequest}
     * @return {@link Response}
     */
    @Override
    public Response getMySub(ListBlogRequest request) {
        String key = RedisKeyTool.buildFansFeedKey(request.getAid());
        Set set = redisTemplate.opsForZSet().reverseRange(key, request.getMysqlStart(), request.getMysqlEnd());
        if (StringTool.isBlank(set)) {
            return Response.create();
        }
        List list = blogRepository.findAllById(set);
        return Response.create(list);
    }
}
